#include <iostream>
#include <vector>
using namespace std;

class ClsSegmentTree {
private:
    vector<int> vecTree;
    vector<int> arrLazyMarks;
    int intLen;

    void Build(int intNode, int intStart, int intEnd, const vector<int>& vecArr) {
        if (intStart == intEnd) {
            vecTree[intNode] = vecArr[intStart];
        } else {
            int intMid = (intStart + intEnd) / 2;
            Build(intNode * 2, intStart, intMid, vecArr);
            Build(intNode * 2 + 1, intMid + 1, intEnd, vecArr);
            vecTree[intNode] = vecTree[intNode * 2] + vecTree[intNode * 2 + 1];
        }
        arrLazyMarks[intNode] = 0;
    }

    void PushDown(int intNode, int intStart, int intEnd) {
        if (arrLazyMarks[intNode] != 0) {
            int intMid = (intStart + intEnd) / 2;
            vecTree[intNode * 2] += arrLazyMarks[intNode] * (intMid - intStart + 1);
            arrLazyMarks[intNode * 2] += arrLazyMarks[intNode];
            vecTree[intNode * 2 + 1] += arrLazyMarks[intNode] * (intEnd - intMid);
            arrLazyMarks[intNode * 2 + 1] += arrLazyMarks[intNode];
            arrLazyMarks[intNode] = 0;
        }
    }

    void UpdateRange(int intNode, int intStart, int intEnd, int intLeft, int intRight, int intValue) {
        if (intRight < intStart || intEnd < intLeft) {
            return;
        }
        if (intLeft <= intStart && intEnd <= intRight) {
            vecTree[intNode] += (intEnd - intStart + 1) * intValue;
            arrLazyMarks[intNode] += intValue;
            return;
        }
        PushDown(intNode, intStart, intEnd);
        int intMid = (intStart + intEnd) / 2;
        UpdateRange(intNode * 2, intStart, intMid, intLeft, intRight, intValue);
        UpdateRange(intNode * 2 + 1, intMid + 1, intEnd, intLeft, intRight, intValue);
        vecTree[intNode] = vecTree[intNode * 2] + vecTree[intNode * 2 + 1];
    }

    int QueryRange(int intNode, int intStart, int intEnd, int intLeft, int intRight) {
        if (intRight < intStart || intEnd < intLeft) {
            return 0;
        }
        if (intLeft <= intStart && intEnd <= intRight) {
            return vecTree[intNode];
        }
        PushDown(intNode, intStart, intEnd);
        int intMid = (intStart + intEnd) / 2;
        int intLeftValue = QueryRange(intNode * 2, intStart, intMid, intLeft, intRight);
        int intRightValue = QueryRange(intNode * 2 + 1, intMid + 1, intEnd, intLeft, intRight);
        return intLeftValue + intRightValue;
    }

public:
    ClsSegmentTree(const vector<int>& vecArr) {
        intLen = vecArr.size();
        vecTree.resize(4 * intLen);
        arrLazyMarks.resize(4 * intLen);
        Build(1, 0, intLen - 1, vecArr);
    }

    void UpdateRangeValues(int intLeft, int intRight, int intValue) {
        UpdateRange(1, 0, intLen - 1, intLeft, intRight, intValue);
    }

    void UpdateSingleElement(int intIdx, int intValue) {
        int intCurrentValue = QuerySingleValue(intIdx);
        UpdateRangeValues(intIdx, intIdx, intValue - intCurrentValue);
    }

    int QuerySingleValue(int intIdx) {
        return QueryRangeValues(intIdx, intIdx);
    }

    int QueryRangeValues(int intLeft, int intRight) {
        return QueryRange(1, 0, intLen - 1, intLeft, intRight);
    }
};

int main() {
    vector<int> vecArr = {1, 3, 5, 7, 9};
    ClsSegmentTree objSegmentTree(vecArr);

    cout << "Sum from 0 to 4: " << objSegmentTree.QueryRangeValues(0, 4) << endl;

    objSegmentTree.UpdateRangeValues(1, 3, 2);
    cout << "Sum from 0 to 4 after update 1-3: " << objSegmentTree.QueryRangeValues(0, 4) << endl;

    objSegmentTree.UpdateSingleElement(2, 10);
    cout << "Sum from 0 to 4 after update index 2: " << objSegmentTree.QueryRangeValues(0, 4) << endl;

    cout << "Sum from 1 to 3: " << objSegmentTree.QueryRangeValues(1, 3) << endl;

    return 0;
}
